﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;

using ProjectBase.Core;
using ProjectBase.Mvc;

using Survey.Common;
using Survey.Common.Business;
using Survey.Common.Business.Services;
using Survey.Common.Data.Services;
using Survey.Entity.Services;

namespace Survey.Business.Services
{
    /// <summary>
    ///     All Business checks for 'Article' on CRUD operations
    ///     are nested and encapsulated in this ArticleFacade
    /// </summary>
    public class ArticleFacade : BaseFacade<Article, int, ArticleFilter, IArticleDao>, IArticleFacade
    {
        #region IBaseFacade<T> override - PROTOTYPE
        /// <summary>
        ///     Prototype design pattern - in practice.
        ///     The central and only point for creating new entity of type Article (prototype).
        ///     Returns new transient entity 'Article'
        ///     - some Properties are preset to business defaults.
        ///     (Business rules therefore should be easier to meet)
        /// </summary>
        /// <returns>new entity 'Article' transient</returns>
        public override Article CreateNew()
        {
            var entity = new Article
            {
                Code = string.Empty,
                Title = string.Empty,
                Description = string.Empty,
                Text = string.Empty,
                IsVisible = false,
                ShowComment = true,
                ArticleCategory = ArticleCategoryFacade.GetByCode(Str.Business.CodeLists.Any),
                ArticleGroup = ArticleGroupFacade.GetByCode(Str.Business.CodeLists.Any)
            };
            return entity;
        }
        #endregion IBaseFacade<T> override - PROTOTYPE

        #region IBaseFacade override
        public override Article Add(Article entity)
        {
            if (entity.Is())
            {
                entity.CreationDate = DateTime.Now;
                entity.LastUpdateDate = DateTime.Now;
            }
            return base.Add(entity);
        }

        public override Article Update(Article entity)
        {
            if (entity.Is())
            {
                entity.LastUpdateDate = entity.LastUpdateDate < DateTime.Now // to allow to set Update
                                            ? DateTime.Now
                                            : entity.LastUpdateDate;
                if (entity.ReleaseDate.IsNull()
                    && entity.IsVisible)
                {
                    entity.ReleaseDate = DateTime.Now;
                }
            }
            return base.Update(entity);
        }

        public override void Delete(Article entity)
        {
            base.Delete(entity);
            AttachmentFacade.ClearAttachments(entity);
        }
        #endregion IBaseFacade override

        #region IArticleFacade
        /// <summary>
        ///     Returns the Article with provided code.
        ///     Null if nothing is found
        /// </summary>
        /// <param name = "code"></param>
        /// <returns></returns>
        public virtual Article GetByCode(string code)
        {
            if (code.IsEmpty())
            {
                this.PublishWarning("There was no code provided");
                return null;
            }

            var filter = new ArticleFilter
            {
                CodeExact = code,
                MaxRowsPerPage = 1,
            };

            var document = Dao.Find(filter).FirstOrDefault();

            if (document.IsNull())
            {
                this.PublishWarning("There was no Article found for provided code '{0}'", code);
            }
            return document;
        }
        #endregion IArticleFacade

        #region IArticleFacade - Attachments
        /// <summary>
        ///     Returns all files, which belongs to the provided entity
        /// </summary>
        /// <param name = "entity"></param>
        /// <returns></returns>
        public virtual IEnumerable<Attachment> GetAttachments(Article entity)
        {
            if (entity.IsNull())
            {
                this.PublishError("CannotGetFilesForNullArticle");
                return null;
            }
            return AttachmentFacade.GetByArticle(entity);
        }

        /// <summary>
        ///     Attached files are stored,
        ///     complete list of existing attachments is returned
        /// </summary>
        /// <param name = "entity"></param>
        /// <param name = "attachments"></param>
        /// <returns></returns>
        public virtual IEnumerable<Attachment> UploadFiles(Article entity, IEnumerable<Attachment> attachments)
        {
            if (entity.IsNull())
            {
                this.PublishError("CannotUploadFileForNullArticle");
                return null;
            }
            if (attachments.IsNull())
            {
                this.PublishError("AttachmentsCollectionCannotBeNull");
                return null;
            }

            foreach (var attachment in attachments)
            {
                attachment.Article = entity;
                AttachmentFacade.AddOrUpdate(attachment);
            }

            return GetAttachments(entity);
        }

        /// <summary>
        ///     Removes the file with the 'fileName' provided.
        ///     This file must belong to the provided Article entity.
        ///     The list fo remaining Attachments is returned
        /// </summary>
        /// <param name = "entity">Article 'containing' this attachment</param>
        /// <param name = "fileName"></param>
        /// <returns></returns>
        public virtual IEnumerable<Attachment> DeleteFile(Article entity, string fileName)
        {
            if (entity.IsNull())
            {
                this.PublishError("CannotDeleteFileForNullArticle");
                return null;
            }
            if (fileName.IsEmpty())
            {
                this.PublishError("FileNameCannotBeNullNorEmpty");
                return null;
            }

            var file = AttachmentFacade.GetByName(fileName, entity);
            if (file.Is())
            {
                AttachmentFacade.Delete(file);
            }

            return GetAttachments(entity);
        }
        #endregion IArticleFacade - Attachments

        #region Validate
        #endregion Validate

        #region properties
        /// <summary>
        ///     Allowes LAZILY use AttachmentFacade (get) or Ioc (set)
        /// </summary>
        public virtual IAttachmentFacade AttachmentFacade { protected get; set; }

        /// <summary>
        ///     Allowes LAZILY use ArticleCategoryFacade (get) or Ioc (set)
        /// </summary>
        public virtual IArticleCategoryFacade ArticleCategoryFacade { protected get; set; }

        /// <summary>
        ///     Allowes LAZILY use ArticleGroupFacade (get) or Ioc (set)
        /// </summary>
        public virtual IArticleGroupFacade ArticleGroupFacade { protected get; set; }
        #endregion properties
    }
}